const Joi = require('joi');
// 导出joi
export const JoiObject = Joi;

/**
 * 普通控制器
 */
export class frontendController {
	constructor(ctx) {
		this.$dx = ctx;
	}
	//取当前控制器对于的service
	get currentService() {
		let service = this.$dx.service;
		//自动获取当前控制器对于的service
		let controller = this.$dx.request.controller;
		controller = controller.replace(/\./g, '/');
		for (let item of controller.split('/')) {
			service = service[item];
		}
		return service;
	}
}

/**
 * 后台控制器
 */
export class backendController {
	constructor(ctx) {
		this.$dx = ctx;
		this.abortEarly = true;
		this.allowUnknown = true;
		this.dto = null;
		this.multiFields = ['switch', 'enable'];
		this.indexWith = [];
		this.listWith = [];
		this.fields = [];
	}
	//取当前控制器对于的service
	get currentService() {
		let service = this.$dx.service;
		//自动获取当前控制器对于的service
		let controller = this.$dx.request.controller;
		controller = controller.replace(/\./g, '/');
		for (let item of controller.split('/')) {
			service = service[item];
		}
		return service;
	}
	//增加
	async add(data) {
		if (this.dto !== null) {
			const schema = Joi.object(this.dto);
			const {
				error
			} = schema.validate(data, {
				// false：表示对所有字段进行校验错误；如果不定义，只要发现不合法的字段就会停止校验
				abortEarly: this.abortEarly,
				// 允许验证被对象包含没有定义校验规则的未知字段，否则会认为被校验数据不通过
				allowUnknown: this.allowUnknown,
			});
			if (error) {
				return this.$dx.fail(error.message);
			}
		}
		let id = await this.currentService.insert(data);
		if (id) {
			return this.$dx.success(this.$dx.$t('successfully added'), id);
		}
		return this.$dx.fail(this.$dx.$t('failed to add'));
	}
	// 编辑
	async edit(data) {
		if (this.dto !== null) {
			const schema = Joi.object(this.dto);
			const {
				error
			} = schema.validate(data, {
				// false：表示对所有字段进行校验错误；如果不定义，只要发现不合法的字段就会停止校验
				abortEarly: this.abortEarly,
				// 允许验证被对象包含没有定义校验规则的未知字段，否则会认为被校验数据不通过
				allowUnknown: this.allowUnknown,
			});
			if (error) {
				return this.$dx.fail(error.message);
			}
		}
		if (!data._id) {
			return this.$dx.fail(this.$dx.$t('parameter error'));
		}
		//查询数据
		let row = await this.currentService.where('_id', data._id).find();
		if (!row) {
			return this.$dx.fail(this.$dx.$t('record not found'));
		}
		//去更新
		let status = await this.currentService.update(data);
		if (status) {
			return this.$dx.success(this.$dx.$t('edit succeeded'));
		}
		return this.$dx.fail(this.$dx.$t('edit failed'));
	}
	// 删除
	async del({
		ids,
		id
	}) {
		if (!ids && !id) {
			return this.$dx.fail(this.$dx.$t('parameter error'));
		}
		let param = ids || id;
		if (typeof param === 'string') {
			param = param.includes(',') ? param.split(',') : [param];
		}
		//符合条件的
		let rows = await this.currentService.where('_id', 'in', param).delete();
		if (!rows) {
			return this.$dx.fail(this.$dx.$t('delete failed'));
		}
		return this.$dx.success(this.$dx.$t('deletion succeeded'));
	}
	//列表
	async index(params) {
		let {
			page = 1, size = 10, order, sort, selectPage
		} = params;
		for (let key of ['page', 'size', 'order', 'sort', 'selectPage']) {
			Reflect.deleteProperty(params, key);
		}
		page = page - 1;
		page = page < 0 ? 0 : page;
		let entity = this.currentService.where(params);
		if (order && typeof order === 'string') {
			entity = entity.order(order, ['asc', 'ASC'].includes(sort) ? 'asc' : 'desc');
		}
		if (this.indexWith.length > 0) {
			entity = entity.with(this.indexWith);
		}
		let list = await entity
			.field(this.fields)
			.limit(size)
			.skip(page * size)
			.select();
		//下拉选择
		if (selectPage && list.length < 2) {
			const moreList = await this.currentService.limit(size).field(this.fields).select();
			// 去重
			list = [...list, ...moreList.filter((item) => !list.some((i) => i._id === item._id))];
		}
		let total = await this.currentService.where(params).count();
		return this.$dx.success(this.$dx.$t('operation succeeded'), {
			list,
			total,
		});
	}
	//单个
	async detail({
		id,
		_id
	}) {
		if (!id && !_id) {
			return this.$dx.fail(this.$dx.$t('parameter error'));
		}
		let row = await this.currentService.where('_id', id || _id).find();
		if (!row) {
			return this.$dx.fail(this.$dx.$t('record not found'));
		}
		return this.$dx.success(this.$dx.$t('operation succeeded'), row);
	}
	//批量
	async multi({
		field,
		value,
		id,
		_id
	}) {
		if (!field || value === void 0 || (!id && !_id)) {
			return this.$dx.fail(this.$dx.$t('parameter error'));
		}
		if (!this.multiFields.includes(field)) {
			return this.$dx.fail(this.$dx.$t('no permission to operate'));
		}
		// 参数处理
		let ids = id || _id;
		if (typeof ids === 'string') {
			ids = ids.includes(',') ? ids.split(',') : [ids];
		}
		if (!Array.isArray(ids)) {
			return this.$dx.fail(this.$dx.$t('parameter error'));
		}
		// 去重
		ids = [...new Set(ids)];
		//符合条件的
		let list = await this.currentService.where('_id', 'in', ids).select();
		if (list.length !== ids.length) {
			return this.$dx.fail(this.$dx.$t('record not found'));
		}
		let status = false;
		if (ids.length == 1) {
			status = await this.currentService.update({
				_id: ids[0],
				[field]: value
			});
		} else {
			status = await this.currentService.where('_id', 'in', ids).update({
				[field]: value
			});
		}
		if (status) {
			return this.$dx.success(this.$dx.$t('operation succeeded'));
		}
		return this.$dx.fail(this.$dx.$t('operation failed'));
	}
	// 列表，默认返回 2000 条
	async list(params={}) {
		let {
			order,
			sort,
			selectPage,
			limit
		} = params;
		/**********************************************************/
		let slist = [],
			_ids = [];
		if (params._id) {
			slist = await this.currentService
				.where({
					_id: params._id
				})
				.with(this.listWith)
				.limit(1000).select();
			if (typeof params._id == "string") {
				_ids = [params._id];
			} else if (params._id.value && Array.isArray(params._id.value)) {
				_ids = params._id.value;
			}
		}
		/***********************************************************/
		for (let key of ['_id', 'order', 'sort', 'selectPage', 'limit']) {
			Reflect.deleteProperty(params, key);
		}
		limit = limit || 1000;
		if (_ids.length) {
			params._id = {
				op: "nin",
				value: _ids
			};
		}
		/***********************************/
		let list;
		if (selectPage) {
			list = await this.currentService
				.field(this.fields)
				.where(params)
				.with(this.listWith)
				.order(order || '_id', ['asc', 'ASC'].includes(sort) ? 'asc' : 'desc')
				.select();
			//下拉选择
			if (selectPage && list.length < 2) {
				const moreList = await this.currentService.with(this.listWith).field(this.fields).limit(limit)
					.select();
				// 去重
				list = [...list, ...moreList.filter((item) => !list.some((i) => i._id === item._id))];
			}
			return this.$dx.success(this.$dx.$t('operation succeeded'), [...slist, ...list]);
		}
		list = await this.currentService
			.field(this.fields)
			.where(params)
			.with(this.listWith)
			.order(order || '_id', ['asc', 'ASC'].includes(sort) ? 'asc' : 'desc')
			.limit(limit)
			.select();
		if (list.length === limit && limit == 1000) {
			let listTwo = await this.currentService
				.field(this.fields)
				.where(params)
				.with(this.listWith)
				.order(order || '_id', ['asc', 'ASC'].includes(sort) ? 'asc' : 'desc')
				.limit(limit)
				.skip(limit)
				.select();
			list = [...list, ...listTwo];
		}
		return this.$dx.success(this.$dx.$t('operation succeeded'), [...slist, ...list]);
	}
}